/**
Nectarine Utility Project is a software interface for the web system 'demovibes'
Copyright (C) 2010  Alexandre LAURENT

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

website: http://code.google.com/p/nectarine-utility-project/
e-mail: lw.demoscene@gmail.com
**/

#include "song.h"

#include <QList>
#include <QDateTime>
#include <QString>

#include <QByteArray>
#include <QXmlStreamReader>

#include <QDebug>

#include "artist.h"
#include "status.h"

#include "../utils.h"

QDebug operator<<(QDebug dbg, const Song& s)
{
    dbg << "Song(\n";
    dbg << "\tId: " << s.id << "\n";
    dbg << "\tTitle: " << s.title << "\n";
    dbg << "\tLength: " << s.length << "\n";
    dbg << "\tNb Votes: " << s.nbVotes << "\n";
    dbg << "\tNote: " << s.actualNote << "\n";
    dbg << "\tArtists: " << s.artists << "\n";
    dbg << "\tUser: " << s.user << "\n";
    dbg << "\tLast time queued: " << s.lastQueued << "\n";
    dbg << "\tLock: " << s.isLocked << "\n";
    dbg << "\tEnd lock time: " << s.endLockDate << "\n";
    dbg << "\tPouet ID: " << s.pouetId << "\n";
    dbg << "\tStatus: " << statusToString(s.status) << "\n";
    dbg << "\tBitrate: " << s.bitrate << "\n";
    dbg << "\tSample rate: " << s.sampleRate << "\n";
    dbg << "\tType: " << s.type << "\n";
    dbg << "\tPlatform: " << s.platform << "\n";
    dbg << "\tInfo: " << s.info << "\n";
    dbg << ")\n";

    return dbg.space();
}

bool parseSong(QXmlStreamReader& xmlReader, Song& s)
{
    QXmlStreamReader::TokenType nodeType = xmlReader.tokenType();
    bool isOk = true;

    qDebug() << "parseSong";

    while ( (nodeType != QXmlStreamReader::EndElement || xmlReader.name() != "song") && isOk )
    {
        if ( nodeType == QXmlStreamReader::StartElement )
        {
            if ( xmlReader.name() == "song" )
            {
                s.id = xmlReader.attributes().value("id").toString().toUInt();
                if ( xmlReader.attributes().value("locked").toString().toLower() == "true" )
                {
                    s.isLocked = true;
                }
                else
                {
                    s.isLocked = false;
                }
                isOk &= Utils::getXMLStringData(xmlReader,s.title);
            }
            else
            {
                qDebug() << "One tag is not parsed at all -> " << xmlReader.name();
            }
        }

        nodeType = xmlReader.readNext();
    }

    qDebug() << s;

    return isOk;
}

bool parseSongPage(QXmlStreamReader& xmlReader, Song& s)
{
    QXmlStreamReader::TokenType nodeType = xmlReader.tokenType();
    bool isOk = true;

    qDebug() << "parseSongPage";

    while ( (nodeType != QXmlStreamReader::EndElement || xmlReader.name() != "song") && isOk )
    {
        if ( nodeType == QXmlStreamReader::StartElement )
        {
            if ( xmlReader.name() == "song" )
            {
                s.id = xmlReader.attributes().value("id").toString().toUInt();
            }
            else if ( xmlReader.name() == "title" )
            {
                isOk &= Utils::getXMLStringData(xmlReader,s.title);
            }
            else if ( xmlReader.name() == "status" )
            {
                QString statusString;
                isOk &= Utils::getXMLStringData(xmlReader,statusString);
                s.status = statusFactory(statusString);
            }
            else if ( xmlReader.name() == "lastplayed" )
            {
                // ToDo !
            }
            else if ( xmlReader.name() == "bitrate" )
            {
                QString bitrateString;
                isOk &= Utils::getXMLStringData(xmlReader,bitrateString);
                if ( isOk )
                {
                    s.bitrate = bitrateString.toUInt(&isOk);
                }
            }
            else if ( xmlReader.name() == "samplerate" )
            {
                QString sampleRateString;
                isOk &= Utils :: getXMLStringData(xmlReader,sampleRateString);
                if ( isOk )
                {
                    s.sampleRate = sampleRateString.toUInt(&isOk);
                }
            }
            else if ( xmlReader.name() == "rating" )
            {
                s.nbVotes = xmlReader.attributes().value("votes").toString().toUInt();
                if ( s.nbVotes )
                {
                    QString actualNoteString;
                    isOk &= Utils::getXMLStringData(xmlReader,actualNoteString);
                    if ( isOk )
                    {
                        s.actualNote = actualNoteString.toFloat(&isOk);
                    }
                }
            }
            else if ( xmlReader.name() == "info" )
            {
                isOk &= Utils::getXMLStringData(xmlReader,s.info);
            }
            else if ( xmlReader.name() == "songlength" )
            {
                QString songLengthString;
                isOk &= Utils::getXMLStringData(xmlReader,songLengthString);
                if ( isOk )
                {
                    unsigned int length = songLengthString.toUInt(&isOk);
                    if ( isOk )
                    {
                        s.length = QTime(length/3600,length/60,length%60);
                    }
                }
            }
            else if ( xmlReader.name() == "locked")
            {
                QString lockedString;
                isOk &= Utils::getXMLStringData(xmlReader,lockedString);
                if ( isOk )
                {
                    s.isLocked = Utils::booleanFactory(lockedString,&isOk);
                }
            }
            else if ( xmlReader.name() == "locked_until" )
            {
                QString lockDateString;
                isOk &= Utils::getXMLStringData(xmlReader,lockDateString);
                if ( isOk )
                {
                    s.endLockDate = QDateTime::fromString(lockDateString,"yyyy-MM-dd HH:mm:ss");
                }
            }
            else if ( xmlReader.name() == "platform" )
            {
                // We could parse the id?
                isOk &= Utils::getXMLStringData(xmlReader,s.platform);
            }
            else if ( xmlReader.name() == "type" )
            {
                // We could parse the id?
                isOk &= Utils::getXMLStringData(xmlReader,s.type);
            }
            else if ( xmlReader.name() == "pouetid" )
            {
                QString pouetIdString;
                isOk &= Utils::getXMLStringData(xmlReader,pouetIdString);
                if ( isOk )
                {
                    s.pouetId = pouetIdString.toUInt(&isOk);
                }
            }
            else if ( xmlReader.name() == "artists")
            {
                while ( (nodeType != QXmlStreamReader::EndElement || xmlReader.name() != "artists") && isOk )
                {
                    if ( nodeType == QXmlStreamReader::StartElement && xmlReader.name() == "artist" )
                    {
                        Artist a;
                        isOk &= parseArtist(xmlReader,a);
                        s.artists.push_back(a);
                    }

                    nodeType = xmlReader.readNext();
                }
            }
            else if ( xmlReader.name() == "groups" )
            {
                while ( (nodeType != QXmlStreamReader::EndElement || xmlReader.name() != "groups") && isOk )
                {
                    if ( nodeType == QXmlStreamReader::StartElement && xmlReader.name() == "group" )
                    {
                        Group g;
                        isOk &= parseGroup(xmlReader,g);
                        s.groups.push_back(g);
                    }

                    nodeType = xmlReader.readNext();
                }
            }
            else
            {
                qDebug() << "One tag is not parsed at all -> " << xmlReader.name();
            }
        }

        nodeType = xmlReader.readNext();
    }

    qDebug() << s;

    return isOk;
}

bool readSongPage(const QByteArray& streamData, Song& s)
{
    QXmlStreamReader xmlReader(streamData);
    QXmlStreamReader::TokenType nodeType;
    bool isOk = true;

    qDebug() << "Parser :: readSongPage";

    while ( !xmlReader.atEnd() )
    {
        nodeType = xmlReader.readNext();

        if ( nodeType == QXmlStreamReader::StartElement && xmlReader.name() == "song" )
        {
            isOk &= parseSongPage(xmlReader,s);
        }
    }

    return isOk;
}
